package model;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Random;

/**
 * Class Hunter. Hunter is an Actor
 * @author Team X
 * @version 1
 */
public class Hunter implements Actor
{
    // The hunter's field.
    private Field field;
    // The hunter's position in the field.
    private Location location;
    // The hunter's personal information
    public String name;
	// The hunters alive/dead situation.
    private boolean alive;
    // If the hunter is on the map or not
    public boolean placed = false;
    // Creation probability
    public static double creation_probability = 0.005; 
    // The hunter's score of killing rabbits, foxes.
    public int SCORE_RABBIT = 0;
    public int SCORE_FOXES = 0;
    public int SCORE_REDFOXES = 0;
    public int totalScore;
    // Default Maximum amount of hunters - should be set in application.
    public static final int MAX_HUNTERS = 5;
    
    /**
     * Create a hunter. A hunter can be created as a new born (age zero
     * and not hungry) or with a random age and food level.
     * 
     * @param randomAge If true, the hunter will have random age and hunger level.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Hunter(boolean randomAge, Field field, Location location)
    {
    	alive = true;
        this.field = field;
        setLocation(location);
        reset();
    }
    
    /**
     * Create a hunter without location
     * @param field
     */
    public Hunter(Field field)
    {
    	alive = true;
        this.field = field;
    }
    
    /**
     * Makes the Hunter act
     */
    public void act()
    {
        if(isAlive()) 
        {
            // Move towards a source of food if found.
            Location location = getLocation();
            Location newLocation = hunt(location);
            if(newLocation == null) 
            { 
                // No food found - try to move to a free location.
                newLocation = getField().freeAdjacentLocation(location);
            }
            // See if it was possible to move.
            if(newLocation != null) 
            {
                setLocation(newLocation);
            }
            /*else 
            {
                // Overcrowding.
                setDead();
            } */
        }
    }
    
    /**
     * Tell the hunter to look for rabbits, foxes and bears adjacent to its current location.
     * Only the first live rabbit, fox or bear is eaten.
     * @param location Where in the field it is located.
     * @return Where food was found, or null if it wasn't.
     */
    public Location hunt(Location location)
    {
        Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
             
        while(it.hasNext()) 
        {
            Location where = it.next();
            Object actor = field.getObjectAt(where);
            if(actor instanceof Rabbit) 
            {
                Rabbit rabbit = (Rabbit) actor;
                if(rabbit.isAlive()) 
                { 
                    rabbit.setDead();
                    this.SCORE_RABBIT ++;
                    
                                
                    // Remove the dead rabbit from the field.
                    return where;
                }
            }
            else if (actor instanceof Fox) 
            {
                Fox fox = (Fox) actor;
                if(fox.isAlive()) 
                { 
                    fox.setDead();
                    SCORE_FOXES ++;
                    // Remove the dead rabbit from the field.
                    return where;
                }
            }
            else if (actor instanceof Redfox) 
            {
            	Redfox redfox = (Redfox) actor;
                if(redfox.isAlive()) 
                { 
                	redfox.setDead();
                    SCORE_REDFOXES ++;
                    // Remove the dead rabbit from the field.
                    return where;
                }
            }
            else if (actor instanceof Hunter) 
            {
            	// Don't move.
                return getLocation();
            }
            
            
        }
        
        setTotalScore();
        return null;
    } 
    
    public boolean isPlaced()
    {
    	return placed;
    }

    /**
     * Return the animal's location.
     * @return The animal's location.
     */
    public Location getLocation()
    {
        return location;
    }
    
    /**
     * Return the animal's field.
     * @return The animal's field.
     */
    public Field getField()
    {
        return field;
    }
    
    /**
     * Place the animal at the new location in the given field.
     * @param newLocation The animal's new location.
     */
    public void setLocation(Location newLocation)
    {
        if(location != null) 
        {
            field.clear(location);
        }
        location = newLocation;
        field.place(this, newLocation);
    }
    

    /**
     * Change class characteristics
     */
    public static void changeCharacteristics(String itemToChange, double value) 
    {
    	/*if (itemToChange.equals("max_litter_size"))
    		max_litter_size = (int)value;    	*/
    }

    /**
     * Reset class characteristics to default
     */
	public void reset() 
	{
	    //max_litter_size = DEF_MAX_LITTER_SIZE;		
	}
	
	/**
	 * Living state
	 * @return boolean alive
	 */
	public boolean isAlive()
	{ return alive; }
	
	/**
	 * Set dead
	 */
	public void setDead()
	{ alive = false; }
	
	public void setTotalScore()
	{
		this.totalScore = this.SCORE_RABBIT + this.SCORE_FOXES + this.SCORE_REDFOXES;
	}
	
	public int getTotalScore()
	{
		return this.totalScore;
	}
	
	public String getName()
	{
		return name;
	}}
	
